package unwdmi.util;

import java.util.ArrayList;
import java.util.Queue;
import java.util.Set;

import unwdmi.cache.Cache;
import unwdmi.dto.MeasurementDTO;
/**
 * The validator is used to validate Measurements Objects
 * @author Stephan E G Veenstra
 *
 */
public class CopyOfValidator {

	private Cache cache;
	
	public CopyOfValidator() {
		this.cache = new Cache(30);
	}
	/**
	 * Validate a Measurement object and return it fixed
	 * @param measurement
	 * @return
	 */
	public MeasurementDTO validate(MeasurementDTO measurement){
		
		cache.addMeasurements(measurement);
		
		// TODO VALIDATE temp!
		Queue<MeasurementDTO> measurements = this.cache.getMeasurements(measurement.getSTN());
//		double[] set = new double[measurements.size()];
//		int i;
		
		double temp = measurement.getTEMP();
		double highest = getHighestTemp(measurement.getSTN());
		double lowest = getLowestTemp(measurement.getSTN());
		double diff = highest-lowest;
		double max = cache.getMeasurements(measurement.getSTN()).peek().getTEMP() + diff/5;
		double min = cache.getMeasurements(measurement.getSTN()).peek().getTEMP() - diff/5;
		
		if(temp > max)
			measurement.setTEMP(max);
		else if(temp < min)
			measurement.setTEMP(min);
		
		if(measurement.getDEWP() == null){
			System.out.println("DEWP corrected from " + measurement.getDEWP() + " -> " + cache.getMeasurements(measurement.getSTN()).peek().getDEWP());
			measurement.setDEWP(cache.getMeasurements(measurement.getSTN()).peek().getDEWP());
		}
		if(measurement.getSTP() == null){
			ArrayList<Double> set = new ArrayList<Double>();
			for(MeasurementDTO m : measurements) {
				set.add(m.getSTP());
			};
			measurement.setSTP(this.getExtrapolationBySet(set.toArray()));
		}
		if(measurement.getSLP() == null){
			ArrayList<Double> set = new ArrayList<Double>();
			for(MeasurementDTO m : measurements) {
				set.add(m.getSTP());
			};
			measurement.setSTP(this.getExtrapolationBySet(set.toArray()));
		}
		if(measurement.getVISIB() == null){
			ArrayList<Double> set = new ArrayList<Double>();
			for(MeasurementDTO m : measurements) {
				set.add(m.getSTP());
			};
			measurement.setVISIB(this.getExtrapolationBySet(set.toArray()));
		}
		if(measurement.getWDSP() == null){
			ArrayList<Double> set = new ArrayList<Double>();
			for(MeasurementDTO m : measurements) {
				set.add(m.getSTP());
			};
			measurement.setWDSP(this.getExtrapolationBySet(set.toArray()));
		}
		if(measurement.getPRCP() == null){
			ArrayList<Double> set = new ArrayList<Double>();
			for(MeasurementDTO m : measurements) {
				set.add(m.getSTP());
			};
			measurement.setPRCP(this.getExtrapolationBySet(set.toArray()));
		}
		if(measurement.getSNDP() == null){
			ArrayList<Double> set = new ArrayList<Double>();
			for(MeasurementDTO m : measurements) {
				set.add(m.getSTP());
			};
			measurement.setSNDP(this.getExtrapolationBySet(set.toArray()));
		}
		if(measurement.getFRSHTT() == null){			
			measurement.setFRSHTT(cache.getMeasurements(measurement.getSTN()).peek().getFRSHTT());
		}
		if(measurement.getCLDC() == null){
			ArrayList<Double> set = new ArrayList<Double>();
			for(MeasurementDTO m : measurements) {
				set.add(m.getSTP());
			};
			measurement.setCLDC(this.getExtrapolationBySet(set.toArray()));
		}
		if(measurement.getWNDDIR() == null){
			ArrayList<Double> set = new ArrayList<Double>();
			for(MeasurementDTO m : measurements) {
				set.add(m.getSTP());
			};
			measurement.setWNDDIR((int)this.getExtrapolationBySet(set.toArray()));
		}
		
		
		return measurement;
	}
	
	private Double getLowestTemp(int station) {
		Queue<MeasurementDTO> m = cache.getMeasurements(station);
		if(m == null)
			return null;
		else{
			Double lowest = null;
			for(MeasurementDTO dto : m){
				if(lowest == null)
					lowest = dto.getTEMP();
				else if(lowest > dto.getTEMP())
					lowest = dto.getTEMP();
			}
			return lowest;
		}
	}
	private Double getHighestTemp(int station) {
		Queue<MeasurementDTO> m = cache.getMeasurements(station);
		if(m == null)
			return null;
		else{
			Double highest = null;
			for(MeasurementDTO dto : m){
				if(highest == null)
					highest = dto.getTEMP();
				else if(highest < dto.getTEMP())
					highest = dto.getTEMP();
			}
			return highest;
		}
	}
	/**
	 * 
	 */
	private double getExtrapolationBySet(Object[] set) {
		int i = 1;
		for(; i < set.length-1; i++) {
			set[i] = ((double)set[i] - (double)set[i-1]) + (double)set[i]; 
			System.out.println(set[i]);
		};
		return (double)set[i];
	};
	
}
